<!--创建时间：2021/11/12 9:17 描述： -->
<template>
  <div class="index-class">
    <CodeMirror v-model="codeSync" :options="cmOptions" @ready="onCmReady" ref="codemirrorRef"/>
    <el-button @click="autoFormatSelection" type="primary">格式化</el-button>
  </div>
</template>
<!--使用ts写vue，这里的语言要修改为ts，其他的位置没有改变，写tsx语言就改成tsx-->
<script lang="ts">
import {Component, PropSync, Vue,Ref} from 'vue-property-decorator'
import sqlFormatter from "sql-formatter";
//@ts-ignore
import { codemirror as CodeMirror } from 'vue-codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/theme/dracula.css';
import 'codemirror/mode/sql/sql.js' // 对于sql模式的支持
import 'codemirror/keymap/sublime.js'
import 'codemirror/addon/hint/show-hint.css'
import 'codemirror/addon/hint/show-hint.js'
import 'codemirror/addon/hint/sql-hint.js'
import 'codemirror/addon/scroll/annotatescrollbar.js'
import 'codemirror/addon/search/matchesonscrollbar.js'
import 'codemirror/addon/search/match-highlighter.js'
import 'codemirror/addon/search/jump-to-line.js'
import 'codemirror/addon/selection/active-line.js'

import 'codemirror/addon/dialog/dialog.js'
import 'codemirror/addon/dialog/dialog.css'
import 'codemirror/addon/search/searchcursor.js'
import 'codemirror/addon/search/search.js'

// 折叠
import 'codemirror/addon/fold/foldgutter.css'
import 'codemirror/addon/fold/foldcode'
import 'codemirror/addon/fold/foldgutter'
import 'codemirror/addon/fold/brace-fold'
import 'codemirror/addon/fold/comment-fold'

import {EditorConfiguration,Editor} from 'codemirror'

export interface MyEditorConfiguration extends EditorConfiguration{
  foldGutter:boolean
}

/*这个装饰器里面写引入的组件和生命周期函数，当然，生命周期函数也是可以写在class类里面*/
@Component({
  components: {CodeMirror}
})
/*这里定义的class一定要继承vue，记不住就直接模仿，class名就是之前的name属性值*/
export default class SqlEditComponents extends Vue {
  @Ref()
  private codemirrorRef: CodeMirror
  get codemirror(){
    return this.codemirrorRef.codemirror as any
  }

  private cmOptions: MyEditorConfiguration = {
    mode: 'text/x-sql', //实现sql代码高亮
    lineNumbers: true,
    theme: 'dracula',
    keyMap: 'sublime',
    extraKeys: {'Ctrl': 'autocomplete'},
    lineWrapping: true, //是否换行
    gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'], //添加行号栏，折叠栏
    foldGutter: true, //是否折叠
  }

  onCmReady(cm: Editor) {
    cm.on('keypress', () => {
      cm.showHint()
    })
  }

  private position_initail_y = 0
  private position_y = 0

  changeEditorMove(event: MouseEvent) {
    // 1. 记录鼠标最后停止的位置
    this.position_y = event.y
    // 2. 实时更新当前已经移动了多少
    const moveLength = Math.max(SqlEditComponents.MIN_HEIGHT, SqlEditComponents.MIN_HEIGHT + (this.position_y - this.position_initail_y))
    this.codemirror.setSize('height', moveLength)
  }

  getSelectedRange() {
    return { from: this.codemirror.getCursor(true), to: this.codemirror.getCursor(false) };
  }
  changeEditorHeight(event:MouseEvent) {
    // 防止触发drag事件
    if (event.stopPropagation) event.stopPropagation();
    if (event.preventDefault) event.preventDefault();
    // 1. 记录当前坐标Y的位置，用于随时更新高度
    this.position_initail_y = event.y
    // 注册鼠标滑动事件
    document.body.addEventListener('mousemove', this.changeEditorMove)
    // mouseup会消失，具体表现就是，鼠标按下，抬起后，编辑器高度依旧跟着改变，如下摘录自简书
    // 触发了浏览器的 drag 操作，导致mouseup丢失。
    // 由于鼠标离开了操作的区域，触发了mouseleave导致mouseup丢失。
    document.body.addEventListener('mouseup', this.releaseMouse)
  }
  getEditorHeight() {
    // @ts-ignore
    const el = this.$refs.codemirror.$el as HTMLElement
    return el.offsetHeight
  }
  releaseMouse() {
    // 当鼠标抬起，此时不再计算实时的距离，清除刚才的事件
    document.body.removeEventListener('mousemove', this.changeEditorMove)
    document.body.removeEventListener('mouseup', this.releaseMouse)
  }
  autoFormatSelection() {
    let str = sqlFormatter.format(this.codemirror.getValue(), {language: 'sql'});
    this.codemirror.setValue(str);
  }
  /*双向绑定的数据，父组件绑定的是name，子组件使用nameSync*/
  @PropSync('code', {default: 'sqlEdit', type: String}) codeSync!: string
  public static MIN_HEIGHT:number = 350
  createdMethods() {}
  mountedMethods() {
    this.$nextTick(() => {
      this.codemirror.setSize('height', SqlEditComponents.MIN_HEIGHT)
      // 获取当前编辑器的初始高度
      let height= this.codemirrorRef.$el.offsetHeight
      console.log('编辑器初始高度：', height)
    })
  }
  // 在页面创建完执行
  private created() {
    this.createdMethods()
  }
  private mounted() {
    this.mountedMethods()
  }
}
</script>
<!--本地样式-->
<style scoped lang="scss">
.index-class{
}
</style>

